/**
 * Copyright 2024-2024 Huawei Technologies Co., Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef FRAMEWORK_HCL_HCL_MODEL_MANAGER_H
#define FRAMEWORK_HCL_HCL_MODEL_MANAGER_H

#include "hiai_types.h"
#include "hiai_execute_option_types.h"
#include "c/hiai_error_types.h"
#include "c/hiai_c_api_export.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @brief 创建模型管理指针实例
 *
 * 本方法提供模型管理指针的创建，在模型加载、推理等操作前，需要调用。
 * 模型卸载后，不需要此指针实例时，调用{@link HIAI_HCL_ModelManager_Destroy}进行销毁，否则将造成内存泄漏。
 *
 * @return 执行成功返回{@link HIAI_MR_ModelManager}指针实例，失败返回空指针
 * @see HIAI_HCL_ModelManager_Destroy
 */
AICP_C_API_EXPORT HIAI_MR_ModelManager* HIAI_HCL_ModelManager_Create();

/**
 * @brief 销毁模型管理指针实例
 *
 * 销毁通过{@link HIAI_HCL_ModelManager_Create}创建的模型管理指针实例，传入指针的引用即可。若不调用，将造成内存泄漏。
 *
 * @param [in] manager {@link HIAI_MR_ModelManager}指针实例的引用，非空
 */
AICP_C_API_EXPORT void HIAI_HCL_ModelManager_Destroy(HIAI_MR_ModelManager** manager);

/**
 * @brief 加载模型
 *
 * 此接口提供模型加载，通过加载选项{@link HIAI_MR_ModelInitOptions}的设置，可调整设备的频率。
 * 若设置监听{@link HIAI_MR_ModelManagerListener}，推理时可使用异步推理接口{@link HIAI_HCL_ModelManager_RunAsyncV3}。
 * 模型推理全部结束后，使用{@link HIAI_HCL_ModelManager_Deinit}对模型进行卸载，降低进程常驻内存。
 *
 * @param [in] manager {@link HIAI_MR_ModelManager}指针实例，非空，否则返回失败
 * @param [in] options 加载参数{@link HIAI_MR_ModelInitOptions}指针实例，可选（不需要时填入空指针）
 * @param [in] builtModel {@link HIAI_MR_BuiltModel}指针实例，非空，否则返回失败
 * @param [in] listener {@link HIAI_MR_ModelManagerListener}指针实例，可选（不需要时填入空指针），异步使能时需要设置
 * @return 函数执行结果状态。执行成功返回HIAI_SUCCESS；失败返回具体错误码，具体失败错误码可参考{@link HIAI_Status}
 * @see HIAI_HCL_ModelManager_Deinit
 */
AICP_C_API_EXPORT HIAI_Status HIAI_HCL_ModelManager_InitV2(HIAI_MR_ModelManager* manager,
    const HIAI_MR_ModelInitOptions* options, const HIAI_MR_BuiltModel* builtModel,
    const HIAI_MR_ModelManagerListener* listener);

/**
 * @brief 设置模型推理优先级
 *
 * 推理任务调度按照优先级进行排序，将推理任务设置在合适的优先级上，可提升推理速度。
 *
 * @param [in] manager {@link HIAI_MR_ModelManager}指针实例，非空，否则返回失败
 * @param [in] priority 模型优先级，详见{@link HIAI_ModelPriority}
 * @return 函数执行结果状态。执行成功返回HIAI_SUCCESS；失败返回具体错误码，具体失败错误码可参考{@link HIAI_Status}
 */
AICP_C_API_EXPORT HIAI_Status HIAI_HCL_ModelManager_SetPriority(
    HIAI_MR_ModelManager* manager, HIAI_ModelPriority priority);

/**
 * @brief 模型同步推理
 *
 * 根据模型输入输出情况，申请tensor的内存，输入输出tensor的内存申请可使用{@link
 * HIAI_MR_NDTensorBuffer}下的create方法，根据需求选择合适的接口。 推理完成，用户不需使用tensor内存后，
 * 需调用{@link HiAI_NDTensorBufferDestroy}销毁申请的每一个tensor内存，否则将造成内存泄漏。
 *
 * @param [in] manager {@link HIAI_MR_ModelManager}指针实例，非空，否则返回失败
 * @param [in] input 模型输入的指针数组，非空，否则返回HIAI_INVALID_PARAM
 * @param [in] inputNum 模型输入的个数
 * @param [in] output 模型输出的指针数组，非空，否则返回HIAI_INVALID_PARAM
 * @param [in] outputNum 模型输出的个数
 * @return 函数执行结果状态。执行成功返回HIAI_SUCCESS；失败返回具体错误码，具体失败错误码可参考{@link HIAI_Status}
 */
AICP_C_API_EXPORT HIAI_Status HIAI_HCL_ModelManager_RunV3(HIAI_MR_ModelManager* manager,
    HIAI_MR_NDTensorBuffer* input[], int32_t inputNum, HIAI_MR_NDTensorBuffer* output[], int32_t outputNum);


/**
 * @brief 模型异步推理
 *
 * 与另一个推理接口{@link HIAI_HCL_ModelManager_RunV3}对比，增加了异步超时以及设置标识，当模型加载时传入了有效的监听{@link
 * HIAI_MR_ModelManagerListener}，推理时可调用此接口。 timeoutInMS为推理的超时时间，即当超过设置的时长，推理还未结束，将触发监听的回调函数{@link
 * onRunDone}，其第二个参数将返回失败。 userData为设置的推理标识，由于是异步推理，用户可在推理时设置本次推理的唯一标识，在发生回调{@link onRunDone}时，
 * 可通过回调函数的第一个参数进行判断是哪一次的推理任务推理结束了。
 * 输入输出的内存{@link HIAI_MR_NDTensorBuffer}在本次推理回调发生响应后再销毁，否则可能会有异常问题的发生。
 * 每次异步推理，建议不要使用同一块内存，否则可能会出现推理结果相同的问题。
 *
 * @param [in] manager {@link HIAI_MR_ModelManager}指针实例，非空，否则返回失败
 * @param [in] input 模型输入的指针数组，非空，否则返回HIAI_INVALID_PARAM
 * @param [in] inputNum 模型输入的个数
 * @param [in] output 模型输出的指针数组，非空，否则返回HIAI_INVALID_PARAM
 * @param [in] outputNum 模型输出的个数
 * @param [in] timeoutInMS 推理的超时时间（单位：毫秒）
 * @param [in] userData 用户推理标识，可选，与回调的onRunDone呼应
 * @return 函数执行结果状态。执行成功返回HIAI_SUCCESS；失败返回具体错误码，具体失败错误码可参考{@link HIAI_Status}
 */
AICP_C_API_EXPORT HIAI_Status HIAI_HCL_ModelManager_RunAsyncV3(HIAI_MR_ModelManager* manager,
    HIAI_MR_NDTensorBuffer* input[], int32_t inputNum, HIAI_MR_NDTensorBuffer* output[], int32_t outputNum,
    int32_t timeoutInMS, void* userData);

/**
 * @brief 动态aipp模型推理。
 *
 * 本方法用于执行动态aipp模型推理。相比非aipp模型推理接口{@link HIAI_HCL_ModelManager_RunAsyncV3}，input/output申请tensor的内存的方式相同。
 * 动态aipp参数输入aippPara内存的申请可使用{@link HIAI_MR_TensorAippPara}的create方法。
 * 通过{@link HIAI_MR_TensorAippPara_SetInputFormat} {@link HIAI_MR_TensorAippPara_SetInputShape}
 * {@linkHIAI_MR_TensorAippPara_SetCscPara} {@link HIAI_MR_TensorAippPara_SetChannelSwapPara}接口设置aipp common参数。
 * 通过{@linkHIAI_MR_TensorAippPara_SetCropPos} {@link HIAI_MR_TensorAippPara_SetCropSize}
 * {@link HIAI_MR_TensorAippPara_SetResizePara} {@link HIAI_MR_TensorAippParaSetPadPara}
 * {@link HIAI_MR_TensorAippPara_SetPadChannelValue} {@link HIAI_MR_TensorAippPara_SetRotateAngle}
 * {@link HIAI_MR_TensorAippPara_SetDtcPixelMeanPara} {@linkHIAI_MR_TensorAippPara_SetDtcPixelMinPara}
 * {@link HIAI_MR_TensorAippPara_SetDtcPixelVarReciPara}等方法设置aipp 的batch参数。
 *
 * @param [in] manager  {@link HIAI_MR_ModelManager}指针实例，非空，否则返回失败
 * @param [in] input image输入的指针数组
 * @param [in] inputNum image输入的个数
 * @param [in] aippPara 动态aipp参数输入的指针数组
 * @param [in] aippParaNum 动态aipp参数输入的个数
 * @param [in] output[] 输出的指针数组
 * @param [in] outputNum 输出的个数
 * @param [in] timeoutInMS 推理超时时间（单位：毫秒），建议异步推理时设置
 * @param [in] userData 用户设置推理标识，建议异步推理时设置
 * @return 函数执行结果状态。执行成功返回HIAI_SUCCESS；失败返回具体错误码，具体失败错误码可参考{@link HIAI_Status}
 */
#ifdef AI_SUPPORT_AIPP_API
AICP_C_API_EXPORT HIAI_Status HIAI_HCL_ModelManager_runAippModelV3(HIAI_MR_ModelManager* manager,
    HIAI_MR_NDTensorBuffer* input[], int32_t inputNum, HIAI_MR_TensorAippPara* aippPara[], int32_t aippParaNum,
    HIAI_MR_NDTensorBuffer* output[], int32_t outputNum, int32_t timeoutInMS, void* userData);
#endif

/**
 * @brief 取消模型异步推理任务
 *
 * 当发起异步推理后，出现用户希望停止推理任务时，可调用此接口。
 *
 * @param [in] manager {@link HIAI_MR_ModelManager}指针实例，非空，否则返回失败
 * @return 函数执行结果状态。执行成功返回HIAI_SUCCESS；失败返回具体错误码，具体失败错误码可参考{@link HIAI_Status}
 */
AICP_C_API_EXPORT HIAI_Status HIAI_HCL_ModelManager_Cancel(HIAI_MR_ModelManager* manager);

/**
 * @brief 加载模型，并使用用户提供的共享内存
 *
 * 此接口与另一个加载接口{@link HIAI_HCL_ModelManager_InitV2}对比，增加了支持传入共享内存
 * {@link HIAI_MR_ModelManagerSharedMemAllocator}，用户可将自己内存池中申请的设备内存，供加载模型时使用，降低内存占用。
 * 用户需提供内存池的申请及释放方法，详见{@link HIAI_MR_ModelManagerSharedMemAllocator}。
 * 模型推理结束，不再需要推理后，使用{@link HIAI_HCL_ModelManager_Deinit}对模型进行卸载，降低进程常驻内存。
 *
 * @param [in] manager {@link HIAI_MR_ModelManager}指针实例，非空，否则返回失败
 * @param [in] options 加载参数{@link HIAI_MR_ModelInitOptions}指针实例，可选（不需要时填入空指针）
 * @param [in] builtModel {@link HIAI_MR_BuiltModel}指针实例，非空，否则返回失败
 * @param [in] listener {@link HIAI_MR_ModelManagerListener}指针实例，可选（不需要时填入空指针），异步使能时需要设置
 * @param [in] allocator {@link HIAI_MR_ModelManagerSharedMemAllocator}指针实例，非空，否则返回失败
 * @return 函数执行结果状态。执行成功返回HIAI_SUCCESS；失败返回具体错误码，具体失败错误码可参考{@link HIAI_Status}
 */
#ifdef AI_SUPPORT_USER_MEM
AICP_C_API_EXPORT HIAI_Status HIAI_HCL_ModelManager_InitWithSharedMemAllocator(HIAI_MR_ModelManager* manager,
    const HIAI_MR_ModelInitOptions* options, const HIAI_MR_BuiltModel* builtModel,
    const HIAI_MR_ModelManagerListener* listener, const HIAI_MR_ModelManagerSharedMemAllocator* allocator);
#endif

/**
 * @brief 获取modelId
 *
 * 该方法用于获取模型Id，模型加载完成后会创建一个执行器，生成一个客户端唯一的ID标记当前模型，用户通过该接口获取对应的ID
 * 之后可以进行相关的操作，比如设置模型优先级等。
 *
 * @param [in] manager {@link HIAI_MR_ModelManager}指针实例，非空，否则返回失败
 * @param [out] modelID 模型ID
 * @return 函数执行结果状态。执行成功返回HIAI_SUCCESS；失败返回具体错误码，具体失败错误码可参考{@link HIAI_Status}
 */
AICP_C_API_EXPORT HIAI_Status HIAI_HCL_ModelManager_GetModelID(HIAI_MR_ModelManager* manager, uint32_t* modelID);

/**
 * @brief 卸载模型
 *
 * 模型不需推理计算后，需调用本接口进行模型的卸载，否则内存一直占用。
 *
 * @param [in] manager {@link HIAI_MR_ModelManager}指针实例，非空，否则返回失败
 * @return 函数执行结果状态。执行成功返回HIAI_SUCCESS；失败返回具体错误码，具体失败错误码可参考{@link HIAI_Status}
 */
AICP_C_API_EXPORT HIAI_Status HIAI_HCL_ModelManager_Deinit(HIAI_MR_ModelManager* manager);

AICP_C_API_EXPORT HIAI_Status HIAI_HCL_ModelManager_InitWeights(HIAI_MR_ModelManager* manager, const char* weightDir);
AICP_C_API_EXPORT HIAI_Status HIAI_HCL_ModelManager_GetWeightBuffer(HIAI_MR_ModelManager* manager,
    const char* weightName, void** data, size_t* size);
AICP_C_API_EXPORT HIAI_Status HIAI_HCL_ModelManager_FlushWeight(HIAI_MR_ModelManager* manager, const char* weightName,
    size_t offset, size_t size);

#ifdef __cplusplus
}
#endif

#endif  // FRAMEWORK_HCL_HCL_MODEL_MANAGER_H

